<?php

namespace App\Models;

use App\Api\Models\Config;
use App\Http\Library\WeChat\MiniWeChat;
use Dcat\Admin\Traits\HasDateTimeFormatter;
use Eloquent;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Storage;
use Intervention\Image\Facades\Image;
use Laravel\Sanctum\HasApiTokens;

/**
 * App\Models\User
 *
 * @property $id
 * @property $nickname
 * @property $avatar
 * @property $mobile
 * @property $tid 推荐用户ID
 * @property $openid
 * @property int $status 状态:0=启用,1=禁用
 * @property string|null $remember_token
 * @property \Illuminate\Support\Carbon|null $created_at
 * @property \Illuminate\Support\Carbon|null $updated_at
 * @property \App\Models\UserFollow|null $fans
 * @property \App\Models\UserFollow|null $follow
 * @property mixed $school_name
 * @property int|null $notifications_count
 * @property \Illuminate\Database\Eloquent\Collection|\Laravel\Sanctum\PersonalAccessToken[] $tokens
 * @property int|null $tokens_count
 * @property string|null $name 姓名
 * @method static \Database\Factories\UserFactory factory(...$parameters)
 * @method static \Illuminate\Database\Eloquent\Builder|User newModelQuery()
 * @method static \Illuminate\Database\Eloquent\Builder|User newQuery()
 * @method static \Illuminate\Database\Eloquent\Builder|User query()
 * @method static \Illuminate\Database\Eloquent\Builder|User whereAvatar($value)
 * @method static \Illuminate\Database\Eloquent\Builder|User whereCreatedAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder|User whereId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|User whereNickname($value)
 * @method static \Illuminate\Database\Eloquent\Builder|User whereRememberToken($value)
 * @method static \Illuminate\Database\Eloquent\Builder|User whereStatus($value)
 * @method static \Illuminate\Database\Eloquent\Builder|User whereUpdatedAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder|User whereMobile($value)
 * @method static \Illuminate\Database\Eloquent\Builder|User whereName($value)
 * @mixin Eloquent
 * @property string|null $money 余额
 * @property string|null $amount 分销金额
 * @property string|null $used_amount 已提现金额
 * @method static \Illuminate\Database\Eloquent\Builder|User whereMoney($value)
 * @method static \Illuminate\Database\Eloquent\Builder|User whereShopId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|User whereTid($value)
 * @property Worker|null $worker
 * @property ShopUser|null $shop
 * @property-read \App\Models\AgentUser|null $agent
 * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\UserCar[] $cars
 * @property-read int|null $cars_count
 * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\UserCoupon[] $coupons
 * @property-read int|null $coupons_count
 * @property-read \Illuminate\Notifications\DatabaseNotificationCollection|\Illuminate\Notifications\DatabaseNotification[] $notifications
 */
class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable, HasDateTimeFormatter;

    /**
     * The attributes that are mass assignable.
     *
     * @var string[]
     */
    protected $fillable = [
        'nickname',
        'name',
        'mobile',
        'avatar',
        'username',
        'password',
        'status',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array
     */
    protected $casts = [

    ];

    protected $appends = ['openid','level_text'];

    /**
     * The "booted" method of the model.
     *
     * @return void
     */
    protected static function booted()
    {
        static::deleted(function (User $user) {
            Oauth::query()->where("user_id",$user->id)->delete();
        });

        static::created(function (User $user) {

        });

        self::deleting(function (User $user){

        });

    }

    public function weChatRegister($openid,$post = []): User
    {
        $user = new self;
        $user->status = 0;
        if (isset($post['tid'])&&$post['tid']){
            $user->tid = $post['tid'];
        }
        $res = $user->save();
        if ($res){
            Oauth::addData($user->id,$openid,"");
        }
        return $user;
    }

    public function getOpenidAttribute(): string
    {
        $oauth = Oauth::findUserId('wx_app',$this->id);
        return $oauth?$oauth->openid:'';
    }


    public function getLevelTextAttribute(): string
    {
        $text = "";
        $user_id = $this->attributes['id'];
        $exists = UserCard::query()->where("user_id",$user_id)->exists();
        if ($exists){
            $text = "一级分销商";
            $exists1 = self::query()->join('user_cards',"user_cards.user_id","=","users.id")
                ->whereNotNull("users.nickname")->where("users.tid",$user_id)->where("users.status",0)->groupBy("users.id")->exists();
            if ($exists1){
                $text = "二级分销商";
            }
        }
        return $text;
    }

    public function member(): BelongsTo
    {
        return $this->belongsTo(UserCard::class,"id","user_id");
    }

    public function worker(): HasOne
    {
        return $this->hasOne(Worker::class,"user_id","id");
    }

    public function cars(): HasMany
    {
        return $this->hasMany(UserCar::class,"user_id","id");
    }

    public function coupons(): HasMany
    {
        return $this->hasMany(UserCoupon::class,"user_id","id");
    }

    public function shop(): HasOne
    {
        return $this->hasOne(ShopUser::class,"user_id","id");
    }

    public function agent(): HasOne
    {
        return $this->hasOne(AgentUser::class,"user_id","id");
    }

    public static function makePoster($user_id): array
    {
        $disk = Storage::disk(config('admin.upload.disk'));
        $poster_img = Config::getName("poster_img");
        $wechat = MiniWeChat::instance();
        $filename = "user_code_{$user_id}.png";
        $posterName = "poster/user_poster_{$user_id}.png";
        if (!is_dir("./storage/poster")){
            mkdir("storage/poster",0755);
        }
        $cacheImg = Cache::get("poster_img");
        $isChange = $cacheImg!=$poster_img;
        $wechat->createCode($filename,$user_id,"codes",1);
        if (!$disk->exists($posterName)||$isChange){
            $img = Image::make("storage/".$poster_img);
            $height =  539/$img->width()*$img->height();
            $img->resize(539,$height);
            $code = "codes/".$filename;
            $avatar_img = Image::make("storage/".$code)->resize(220,220);
            $img->insert($avatar_img, 'center',0,240);
            $img->save("storage/".$posterName);
            Cache::set("poster_img",$poster_img);
        }
        $data['poster'] = cdn_url($posterName);
        return $data;
    }

    /**
     * 下级用户列表
     * @param $user_id
     * @return array
     */
    public static function getChild($user_id): array
    {
        $items = self::query()->where("tid",$user_id)->get(['id','nickname','avatar']);
        foreach ($items as $item){
            $item->avatar = cdn_url($item->avatar);
            $id = $item->id;
            $item->count = self::query()
                ->whereExists(function ($query) use ($id) {
                    $query->from("payment_orders")->where("pay_status",1)->where("user_id",$id);
                })
                ->where("tid",$item->id)->count();
        }
        return [
            "items"=>$items
        ];
    }

    /**
     * @param int $type 类型 0=后台修改,1=订单金额,2=提现金额
     * @param int $user_id 店铺ID
     * @param float $money 变更金额
     * @param string $remark 备注
     */
    public static function amount(int $type, int $user_id, float $money, string $remark){
        if ($money!=0){
            $user = self::query()->where("id",$user_id)->first();
            if ($user){
                $pre_money = $user->amount;
                $after_money = $user->amount + $money;
                if ($type==2){
                    $used_amount = $user->used_amount + abs($money);
                    $res = self::query()->where("id",$user_id)->update(['amount'=>$after_money,"used_amount"=>$used_amount]);
                }else{
                    $res = self::query()->where("id",$user_id)->update(['amount'=>$after_money]);
                }
                if ($res){
                    UserAmount::create([
                        'type'=>$type,
                        'user_id'=>$user_id,
                        'pre_money'=>$pre_money,
                        'money'=>$money,
                        'after_money'=>$after_money,
                        'remark'=>$remark,
                    ]);
                }
            }
        }
    }

}
